package com.house365.updown.download;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;

import com.house365.core.constant.CorePreferences;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.os.Message;

/**
 *@author py
 *@date 2013-7-19
 *@comment
 */
public class HttpDownloaderManager {
	 public static final String ACTION_DOWNLOAD_COMPLETE = "android.author.cloud.download.DOWNLOAD_COMPLETE";
	 public static final String EXTRA_DOWNLOAD_ID = "extra_download_id";
	public Context mContext = null;

	public static final int MSG_DOWNLOAD_STATUS_COMPLETED = 0;
	public static final int MSG_DOWNLOAD_STATUS_ERROR = 1;
	
	private int connectTimeout = 30 * 1000;
	private int readTimeout = 30 * 1000;
	private Proxy mProxy = null;

	public Map<Long,DownloaderInfo> downloaderInfos =new HashMap<Long,DownloaderInfo>();
	public interface DownloadListener{
		public void onComplete(long id);
		public void onError(long id);
	}

	private DownloadListener downloadListener;
	public HttpDownloaderManager(Context context) {
		this.mContext = context;
		setDefaultHostnameVerifier();
	}
	private Handler mHandler = new Handler() {
		public void handleMessage(Message msg) {
			try {
				switch (msg.what) {
				case MSG_DOWNLOAD_STATUS_COMPLETED:{
					long id = (Long) msg.obj;
					DownloaderInfo info = downloaderInfos.get(id);
					info.setStatus(DownloaderInfo.DOWNLOAD_STATUS_COMPLETED);
					//notify complete
					if(downloadListener!= null){
						downloadListener.onComplete(id);
					}
					break;
				}
				case MSG_DOWNLOAD_STATUS_ERROR:{
					long id = (Long) msg.obj;
					DownloaderInfo info = downloaderInfos.get(id);
					info.setStatus(DownloaderInfo.DOWNLOAD_STATUS_ERROR);
					if(downloadListener!= null){
						downloadListener.onError(id);
					}
					break;
				}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	};
	public DownloaderInfo getDownloaderInfo(long id){
		return downloaderInfos.get(id);
	}
	public void cancelDownload(long id){
		DownloaderInfo info = downloaderInfos.get(id);
		info.setDownloading(false);
	}
	public int tetDownloadInfoStauts(long id){
		DownloaderInfo info = downloaderInfos.get(id);
		return info.getStatus();
	}

	/**
	 * 
	 * 下载文件
	 * @param downloadMessage
	 * @param fileUrl
	 * @param filePath
	 */
	public long downLoadFile(
			final String fileUrl, final String filePath) {
			CorePreferences.DEBUG("downLoadFile,url:"+fileUrl+",local:"+filePath);
		//生成一个下载配置信息
		DownloaderInfo downloaderInfo = new DownloaderInfo();
		final long id = downloaderInfo.getId();
		downloaderInfos.put(id, downloaderInfo);
		
		// 启动进程下载
		new Thread(new Runnable() {
			public void run() {
				if (isDownloadFile(id, fileUrl, filePath)) {
					Message msg = new Message();
					msg.what = MSG_DOWNLOAD_STATUS_COMPLETED;
					msg.obj = id;
					mHandler.sendMessage(msg);
				} else {
					Message msg = new Message();
					msg.what = MSG_DOWNLOAD_STATUS_ERROR;
					msg.obj = id;
					mHandler.sendMessage(msg);
				}
			}
		}).start();
		return id;
	}

	/***
	 * download and return the flag whether download successful
	 * @param context
	 * @param strurl
	 * @param filename
	 * @return
	 */
	public boolean isDownloadFile(long id, String strurl,
			String filename) {
		boolean bRet = false;
		try {
			bRet = urlDownloadToFile(id,strurl, filename);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return bRet;
	}

	/**
	 * set proxy
	 */
	private void detectProxy() {
		ConnectivityManager cm = (ConnectivityManager) mContext
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo ni = cm.getActiveNetworkInfo();
		if (ni != null && ni.isAvailable()
				&& ni.getType() == ConnectivityManager.TYPE_MOBILE) {
			String proxyHost = android.net.Proxy.getDefaultHost();
			int port = android.net.Proxy.getDefaultPort();
			if (proxyHost != null) {
				final InetSocketAddress sa = new InetSocketAddress(proxyHost,
						port);
				mProxy = new Proxy(Proxy.Type.HTTP, sa);
			}
		}
	}

	private void setDefaultHostnameVerifier() {
		HostnameVerifier hv = new HostnameVerifier() {
			public boolean verify(String hostname, SSLSession session) {
				return true;
			}
		};
		HttpsURLConnection.setDefaultHostnameVerifier(hv);
	}


	/**
	 * �����ļ�
	 * 
	 * @param context
	 *            �����Ļ���
	 * @param strurl
	 *            ���ص�ַ
	 * @param path
	 *            ����·��
	 * @return
	 */
	private boolean urlDownloadToFile(long id,String strurl, String path) {
		boolean bRet = false;

		detectProxy();
		InputStream in =null;
		FileOutputStream out =null;
		try {
			URL url = new URL(strurl);
			HttpURLConnection conn = null;
			if (mProxy != null) {
				conn = (HttpURLConnection) url.openConnection(mProxy);
			} else {
				conn = (HttpURLConnection) url.openConnection();
			}
			conn.setConnectTimeout(connectTimeout);
			conn.setReadTimeout(readTimeout);
			conn.setDoInput(true);
			//设置文件大小
			int maxSize = conn.getContentLength();
			DownloaderInfo info =  downloaderInfos.get(id);
			info.setMaxSize(maxSize);
			
			conn.connect();
			in= conn.getInputStream();
			File file = new File(path);
			file.createNewFile();
			out= new FileOutputStream(file);
			byte[] temp = new byte[1024];
			int i = 0;
			while ((i = in.read(temp)) > 0 && info.isDownloading()) {
				out.write(temp, 0, i);
				//刷新下载进度
				info.setNowSize(info.getNowSize()+i);
			}

			bRet = info.isDownloading();

		} catch (IOException e) {
			e.printStackTrace();
			bRet = false;
		} finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return bRet;
	}
	public DownloadListener getDownloadListener() {
		return downloadListener;
	}
	public void setDownloadListener(DownloadListener downloadListener) {
		this.downloadListener = downloadListener;
	}

}
